/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.yangfei.SportAssistant;

import com.yangfei.SportAssistant.content.SportAssistantProviderUtils;
import com.yangfei.SportAssistant.content.Track;
import com.yangfei.SportAssistant.content.TrackDataHub;
import com.yangfei.SportAssistant.content.WaypointCreationRequest;
import com.yangfei.SportAssistant.fragments.ChartSettingsDialog;
import com.yangfei.SportAssistant.io.file.SaveActivity;
import com.yangfei.SportAssistant.io.file.TrackWriterFactory.TrackFileFormat;
import com.yangfei.SportAssistant.mapProvider.CommonLoggerMap;
import com.yangfei.SportAssistant.mapProvider.LoggerMap;
import com.yangfei.SportAssistant.services.ITrackRecordingService;
import com.yangfei.SportAssistant.services.TrackRecordingServiceConnection;
import com.yangfei.SportAssistant.util.ApiAdapterFactory;
import com.yangfei.SportAssistant.util.Constants;
import com.yangfei.SportAssistant.util.PreferencesUtils;
import com.yangfei.SportAssistant.util.TrackRecordingServiceConnectionUtils;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.TabActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.RemoteException;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager.BadTokenException;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
import android.widget.Toast;

import java.util.List;

/**
 * An activity to show the track detail.
 * 
 * @author Leif Hendrik Wilden
 * @author Rodrigo Damazio
 */
public class MainTabActivity extends TabActivity implements OnCheckedChangeListener
{
	private static MainTabActivity instance = null;

	public static MainTabActivity getInstance()
	{
		return instance;
	}

	private enum MenuState
	{
		EMenuNoTrack, EMenuTrackStop, EMenuTrackRecording
	}

	public static final String EXTRA_TRACK_ID = "track_id";
	public static final String EXTRA_WAYPOINT_ID = "waypoint_id";

	private static final String TAG = MainTabActivity.class.getSimpleName();
	private static final String CURRENT_TAG_KEY = "tab";

	private SharedPreferences sharedPreferences;
	private TrackDataHub trackDataHub = null;
	private TrackRecordingServiceConnection trackRecordingServiceConnection = null;

	private long mTrackId;

	private MenuItem stopRecordingMenuItem;
	private MenuItem startRecordingMenuItem;
	private MenuItem insertMarkerMenuItem;
	private MenuItem playMenuItem;
	private MenuItem shareMenuItem;
	private MenuItem sendGoogleMenuItem;
	private MenuItem saveMenuItem;
	private MenuItem editMenuItem;
	private MenuItem deleteMenuItem;
	private MenuItem sensorMenuItem;
	private MenuItem markerMenuItem;
	private MenuItem settingMenuItem;
	private MenuItem helpMenuItem;

	private View mapViewContainer;

	private MenuState mMenuState;

	private boolean startNewRecording = false;
	private long recordingTrackId = -1;

	// for tab group
	private RadioGroup tabGroup;
	private TabHost tabHost;

	public static final int DIALOG_CHART_SETTINGS = 1;
	private ChartSettingsDialog chartSettingsDialog;

	static private Class<?> mMapClass;
	
	private LoggerMap mLoggerMap;

	// Callback when the trackRecordingServiceConnection binding changes.
	private final Runnable bindChangedCallback = new Runnable()
	{
		@Override
		public void run()
		{
			if (!startNewRecording)
			{
				long recordingTrackID = trackRecordingServiceConnection.getRecordingTrackId();
				handleOpenTrack(recordingTrackID);
				return;
			}

			ITrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
			if (service == null)
			{
				Log.d(TAG, "service not available to start a new recording");
				return;
			}
			try
			{
				recordingTrackId = service.startNewTrack();
				updateMenu();
				startNewRecording = false;
				handleOpenTrack(recordingTrackId);
				Toast.makeText(MainTabActivity.this, R.string.track_list_record_success, Toast.LENGTH_SHORT).show();
				Log.d(TAG, "Started a new recording");
			}
			catch (Exception e)
			{
				Toast.makeText(MainTabActivity.this, R.string.track_list_record_error, Toast.LENGTH_LONG).show();
				Log.e(TAG, "Unable to start a new recording.", e);
			}
		}
	};

	/*
	 * Note that sharedPreferenceChangeListener cannot be an anonymous inner
	 * class. Anonymous inner class will get garbage collected.
	 */
	private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener()
	{
		@Override
		public void onSharedPreferenceChanged(SharedPreferences preferences, String key)
		{
			// Note that key can be null
			if (PreferencesUtils.getRecordingTrackIdKey(MainTabActivity.this).equals(key))
			{
				updateMenu();
			}

			if (key.equals(PreferencesUtils.getKey(MainTabActivity.this, R.string.map_source_key)))
			{
				updateMapProvider();
			}
		}
	};

	static public void updateMapProvider()
	{
		UpdateMapTab(instance);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);

		setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
		setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
		ApiAdapterFactory.getApiAdapter().hideTitle(this);
		ApiAdapterFactory.getApiAdapter().configureActionBarHomeAsUp(this);
		setContentView(R.layout.track_tab);

		instance = this;

		sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
		if (sharedPreferences != null)
		{
			sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
		}

		((SportAssistantApplication) getApplication()).mContext = this;
		trackDataHub = ((SportAssistantApplication) getApplication()).getTrackDataHub();
		trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, bindChangedCallback);

		recordingTrackId = PreferencesUtils.getRecordingTrackId(this);
		// mapViewContainer =
		// getLayoutInflater().inflate(R.layout.sportassistant_layout, null);
		mapViewContainer = findViewById(R.layout.sportassistant_layout);
		InitTab();
		mLoggerMap = (LoggerMap)getTabActivity(Constants.TAB_ITEM_MAP);
		
		if (savedInstanceState != null)
		{
			tabHost.setCurrentTabByTag(savedInstanceState.getString(CURRENT_TAG_KEY));
		}

		//overridePendingTransition(R.anim.zoom_enter, R.anim.hold);
		// handleIntent(getIntent());
	}

	private void InitTab()
	{

		tabGroup = (RadioGroup) findViewById(R.id.main_radio);
		tabGroup.setOnCheckedChangeListener(this);

		tabHost = this.getTabHost();

		CreateTab(this);

	}

	static public void CreateTab(TabActivity aTab)
	{
		TabHost tH = aTab.getTabHost();

		TabSpec tabMainUI = tH.newTabSpec(Constants.TAB_ITEM_MAP);
		TabSpec tabInfo = tH.newTabSpec(Constants.TAB_ITEM_INFO);
		TabSpec tabChart = tH.newTabSpec(Constants.TAB_ITEM_CHART);
		TabSpec tabTracks = tH.newTabSpec(Constants.TAB_ITEM_TRACKS);
		TabSpec tabSetting = tH.newTabSpec(Constants.TAB_ITEM_SETTING);

		mMapClass = CommonLoggerMap.getMapClass(aTab);
		tabMainUI.setIndicator(Constants.TAB_ITEM_MAP).setContent(new Intent(aTab, mMapClass));
		tabInfo.setIndicator(Constants.TAB_ITEM_INFO).setContent(new Intent(aTab, StatsActivity.class));
		tabChart.setIndicator(Constants.TAB_ITEM_CHART).setContent(new Intent(aTab, ChartActivity.class));
		tabTracks.setIndicator(Constants.TAB_ITEM_TRACKS).setContent(new Intent(aTab, TrackListActivity.class));
		tabSetting.setIndicator(Constants.TAB_ITEM_SETTING).setContent(new Intent(aTab, SettingsActivity.class));

		tH.addTab(tabMainUI);
		tH.addTab(tabInfo);
		tH.addTab(tabChart);
		tH.addTab(tabTracks);
		tH.addTab(tabSetting);
	}

	static public void UpdateMapTab(TabActivity aTab)
	{
		if (mMapClass != CommonLoggerMap.getMapClass(aTab))
		{
			TabHost tH = aTab.getTabHost();
			int tabNow = tH.getCurrentTab();
			tH.clearAllTabs();
			CreateTab(aTab);
			tH.setCurrentTab(tabNow);
		}
	}

	@Override
	public void onCheckedChanged(RadioGroup group, int checkedId)
	{
		switch (checkedId)
		{
			case R.id.main_map_data:
				tabHost.setCurrentTabByTag(Constants.TAB_ITEM_MAP);
				break;
			case R.id.info:
				tabHost.setCurrentTabByTag(Constants.TAB_ITEM_INFO);
				break;
			case R.id.chart:
				tabHost.setCurrentTabByTag(Constants.TAB_ITEM_CHART);
				break;
			case R.id.tracks:
				tabHost.setCurrentTabByTag(Constants.TAB_ITEM_TRACKS);
				break;
			case R.id.setting:
				tabHost.setCurrentTabByTag(Constants.TAB_ITEM_SETTING);
				break;
			default:
				break;
		}
	}

	public void switchToTab(String tabID)
	{
		// tabHost.setCurrentTabByTag(tabID);

		if (tabID == Constants.TAB_ITEM_MAP)
			tabGroup.check(R.id.main_map_data);
	}

	@Override
	public void onNewIntent(Intent intent)
	{
		super.onNewIntent(intent);
		handleIntent(intent);
	}

	@Override
	protected void onStart()
	{
		super.onStart();

	}

	@Override
	protected void onResume()
	{
		if (trackDataHub != null)
		{
			trackDataHub.start();
		}

		if (trackRecordingServiceConnection != null)
			TrackRecordingServiceConnectionUtils.resume(this, trackRecordingServiceConnection);

		super.onResume();
	}

	protected void onPause()
	{
		if (trackDataHub != null)
		{
			trackDataHub.stop();
		}

		super.onPause();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		super.onSaveInstanceState(outState);
		outState.putString(CURRENT_TAG_KEY, tabHost.getCurrentTabTag());
	}

	@Override
	protected void onStop()
	{
		super.onStop();

	}

	@Override
	protected void onDestroy()
	{
		Log.d(TAG, "onDestroy");

		if (trackRecordingServiceConnection != null)
			trackRecordingServiceConnection.unbind();

		if (trackDataHub != null)
		{
			trackDataHub.Destroy();
			trackDataHub = null;
		}

		super.onDestroy();
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0)
		{
			AlertDialog.Builder alertbBuilder = new AlertDialog.Builder(this);
			alertbBuilder.setTitle(R.string.quit_dialog_title)
			.setMessage(R.string.quit_dialog_text)
					.setPositiveButton(R.string.quit_dialog_yes, new DialogInterface.OnClickListener()
			{
				@Override
				public void onClick(DialogInterface dialog, int which)
				{
					int nPid = android.os.Process.myPid();
					android.os.Process.killProcess(nPid);
				}
			}).setNegativeButton(R.string.quit_dialog_no, new DialogInterface.OnClickListener()
			{

				@Override
				public void onClick(DialogInterface dialog, int which)
				{
					dialog.cancel();
				}
			}).create();
			alertbBuilder.show();
		}
		return true;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		getMenuInflater().inflate(R.menu.track_detail, menu);
		String fileTypes[] = getResources().getStringArray(R.array.file_types);
		menu.findItem(R.id.track_detail_save_gpx).setTitle(getString(R.string.menu_save_format, fileTypes[0]));
		menu.findItem(R.id.track_detail_save_kml).setTitle(getString(R.string.menu_save_format, fileTypes[1]));
		menu.findItem(R.id.track_detail_save_csv).setTitle(getString(R.string.menu_save_format, fileTypes[2]));
		menu.findItem(R.id.track_detail_save_tcx).setTitle(getString(R.string.menu_save_format, fileTypes[3]));

		menu.findItem(R.id.track_detail_share_gpx).setTitle(getString(R.string.menu_share_file, fileTypes[0]));
		menu.findItem(R.id.track_detail_share_kml).setTitle(getString(R.string.menu_share_file, fileTypes[1]));
		menu.findItem(R.id.track_detail_share_csv).setTitle(getString(R.string.menu_share_file, fileTypes[2]));
		menu.findItem(R.id.track_detail_share_tcx).setTitle(getString(R.string.menu_share_file, fileTypes[3]));

		stopRecordingMenuItem = menu.findItem(R.id.track_detail_stop_recording);
		startRecordingMenuItem = menu.findItem(R.id.track_detail_start_recording);
		insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker);
		playMenuItem = menu.findItem(R.id.track_detail_play);
		shareMenuItem = menu.findItem(R.id.track_detail_share);
		sendGoogleMenuItem = menu.findItem(R.id.track_detail_send_google);
		saveMenuItem = menu.findItem(R.id.track_detail_save);
		editMenuItem = menu.findItem(R.id.track_detail_edit);
		deleteMenuItem = menu.findItem(R.id.track_detail_delete);
		sensorMenuItem = menu.findItem(R.id.track_detail_sensor_state);
		markerMenuItem = menu.findItem(R.id.track_detail_markers);
		settingMenuItem = menu.findItem(R.id.track_detail_settings);
		helpMenuItem = menu.findItem(R.id.track_detail_help);

		// item not used
		ShowMenuItem(playMenuItem, false);
		ShowMenuItem(shareMenuItem, false);
		ShowMenuItem(sendGoogleMenuItem, false);
		ShowMenuItem(sensorMenuItem, false);
		ShowMenuItem(settingMenuItem, false);
		ShowMenuItem(helpMenuItem, false);

		updateMenu();
		return true;
	}

	private void ShowMenuItem(MenuItem aItem, boolean aVisible)
	{
		if (aItem != null)
			aItem.setVisible(aVisible);
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu)
	{
		updateMenu();

		String currentTabTag = tabHost.getCurrentTabTag();

		if (menu.findItem(R.id.track_detail_chart_settings) != null)
		{
			menu.findItem(R.id.track_detail_chart_settings).setVisible(Constants.TAB_ITEM_CHART.equals(currentTabTag));
		}
		if (menu.findItem(R.id.track_detail_my_location) != null)
		{
			menu.findItem(R.id.track_detail_my_location).setVisible(Constants.TAB_ITEM_MAP.equals(currentTabTag));
		}

		// Set map or satellite mode
		if (menu.findItem(R.id.track_detail_satellite_mode) != null)
		{
			boolean isSatelliteMode = mLoggerMap != null ? mLoggerMap.isSatelliteView() : false;
			menu.findItem(R.id.track_detail_satellite_mode).setVisible(Constants.TAB_ITEM_MAP.equals(currentTabTag)).setTitle(isSatelliteMode ? R.string.menu_map_mode
					: R.string.menu_satellite_mode);
		}

		return super.onPrepareOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		Intent intent;
		switch (item.getItemId())
		{
		/*
		 * case android.R.id.home: startTrackListActivity(); return true;
		 */
			case R.id.track_detail_stop_recording:
				stopRecording();
				return true;
			case R.id.track_detail_start_recording:
				startRecording();
				return true;
			case R.id.track_detail_insert_marker:
				// TODO: Add insert marker when updating WaypointList to ICS
				return true;
			case R.id.track_detail_play:
				return true;
			case R.id.track_detail_share_map:
				return true;
			case R.id.track_detail_share_fusion_table:
				return true;
			case R.id.track_detail_share_gpx:
				startSaveActivity(TrackFileFormat.GPX, true);
				return true;
			case R.id.track_detail_share_kml:
				startSaveActivity(TrackFileFormat.KML, true);
				return true;
			case R.id.track_detail_share_csv:
				startSaveActivity(TrackFileFormat.CSV, true);
				return true;
			case R.id.track_detail_share_tcx:
				startSaveActivity(TrackFileFormat.TCX, true);
				return true;
			case R.id.track_detail_markers:
				intent = new Intent(this, WaypointsList.class).putExtra("trackid", trackDataHub.getSelectedTrackId());
				startActivityForResult(intent, Constants.SHOW_WAYPOINT);
				return true;
			case R.id.track_detail_send_google:
				return true;
			case R.id.track_detail_save_gpx:
				startSaveActivity(TrackFileFormat.GPX, false);
				return true;
			case R.id.track_detail_save_kml:
				startSaveActivity(TrackFileFormat.KML, false);
				return true;
			case R.id.track_detail_save_csv:
				startSaveActivity(TrackFileFormat.CSV, false);
				return true;
			case R.id.track_detail_save_tcx:
				startSaveActivity(TrackFileFormat.TCX, false);
				return true;
			case R.id.track_detail_edit:
				startActivity(new Intent(this, TrackEditActivity.class).putExtra(TrackEditActivity.EXTRA_TRACK_ID, mTrackId));
				return true;
			case R.id.track_detail_delete:
				long trackId = trackDataHub.getSelectedTrackId();
				deleteTrack(trackId);
				return true;
			case R.id.track_detail_my_location:
				if (mLoggerMap != null)
				{
					mLoggerMap.showMyLocation();
				}
				return true;
			case R.id.track_detail_satellite_mode:
				if (mLoggerMap != null)
				{
					mLoggerMap.setSatelliteView(!mLoggerMap.isSatelliteView());
				}
				return true;
			case R.id.track_detail_chart_settings:
				showDialogSafely(DIALOG_CHART_SETTINGS);
				return true;
			case R.id.track_detail_sensor_state:
				startActivity(new Intent(this, SensorStateActivity.class));
				return true;
			case R.id.track_detail_settings:
				startActivity(new Intent(this, SettingsActivity.class));
				return true;
			case R.id.track_detail_help:
				startActivity(new Intent(this, HelpActivity.class));
				return true;
			default:
				return false;
		}
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, final Intent results)
	{
		if (requestCode != Constants.SHOW_WAYPOINT)
		{
			Log.d(TAG, "Invalid request code: " + requestCode);
			return;
		}
		if (results != null)
		{
			long waypointId = results.getLongExtra(WaypointDetails.WAYPOINT_ID_EXTRA, -1L);
			if (waypointId != -1L)
			{
				if (mLoggerMap != null)
				{
					tabHost.setCurrentTabByTag(Constants.TAB_ITEM_MAP);
					mLoggerMap.showWaypoint(waypointId);
				}
			}
		}
	}

	@Override
	public boolean onTrackballEvent(MotionEvent event)
	{
		if (event.getAction() == MotionEvent.ACTION_DOWN)
		{
			if (TrackRecordingServiceConnectionUtils.isRecording(this, trackRecordingServiceConnection))
			{
				ITrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
				if (trackRecordingService == null)
				{
					Log.e(TAG, "The track recording service is null");
					return true;
				}
				boolean success = false;
				try
				{
					long waypointId = trackRecordingService.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
					if (waypointId != -1L)
					{
						success = true;
					}
				}
				catch (RemoteException e)
				{
					Log.e(TAG, "Unable to insert waypoint", e);
				}
				Toast.makeText(this, success ? R.string.marker_insert_success : R.string.marker_insert_error, success ? Toast.LENGTH_SHORT
						: Toast.LENGTH_LONG).show();
				return true;
			}
		}
		return super.onTrackballEvent(event);
	}

	/**
	 * @return the mapViewContainer
	 */
	public View getMapViewContainer()
	{
		return mapViewContainer;
	}

	/**
	 * Handles the data in the intent.
	 */
	private void handleIntent(Intent intent)
	{
		long trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L);
		long wayPointId = intent.getLongExtra(EXTRA_WAYPOINT_ID, -1L);
		if (trackId != -1L)
		{
			handleOpenTrack(trackId);
			handleOpenWayPoint(wayPointId);
		}

	}

	private void handleOpenWayPoint(long aWId)
	{
		// Get the waypointId
		long waypointId = aWId;
		if (waypointId != -1L)
		{
			if (mLoggerMap != null)
			{
				tabHost.setCurrentTabByTag(Constants.TAB_ITEM_MAP);
				mLoggerMap.showWaypoint(mTrackId, waypointId);
			}
			else
			{
				Log.e(TAG, "MapFragment is null");
			}
		}
	}

	private void handleOpenTrack(long aTId)
	{
		// Get the trackid
		mTrackId = aTId;
		if (mTrackId == -1L)
		{
			/*
			 * startTrackListActivity(); finish();
			 */
		}
		else
		{
			trackDataHub.loadTrack(mTrackId);
		}
	}

	/**
	 * Updates the menu.
	 */
	private void updateMenu()
	{

		if (mTrackId == -1)
		{
			mMenuState = MenuState.EMenuNoTrack;
		}
		else
		{
			if (TrackRecordingServiceConnectionUtils.isRecording(this, trackRecordingServiceConnection))
			{
				mMenuState = MenuState.EMenuTrackRecording;
			}
			else
			{
				mMenuState = MenuState.EMenuTrackStop;
			}
		}
		updateMenuItems(mMenuState);
	}

	/**
	 * Updates the menu items.
	 * 
	 * @param isRecording
	 *          true if recording
	 */
	private void updateMenuItems(MenuState aState)
	{

		switch (aState)
		{
			case EMenuNoTrack:
			{
				ShowMenuItem(stopRecordingMenuItem, false);
				ShowMenuItem(startRecordingMenuItem, true);
				ShowMenuItem(insertMarkerMenuItem, false);
				ShowMenuItem(saveMenuItem, false);
				ShowMenuItem(editMenuItem, false);
				ShowMenuItem(deleteMenuItem, false);
				ShowMenuItem(markerMenuItem, false);

				break;
			}
			case EMenuTrackStop:
			{
				ShowMenuItem(stopRecordingMenuItem, false);
				ShowMenuItem(startRecordingMenuItem, true);
				ShowMenuItem(insertMarkerMenuItem, false);
				ShowMenuItem(saveMenuItem, true);
				ShowMenuItem(editMenuItem, true);
				ShowMenuItem(deleteMenuItem, true);
				ShowMenuItem(markerMenuItem, true);
				break;
			}
			case EMenuTrackRecording:
			{
				ShowMenuItem(stopRecordingMenuItem, true);
				ShowMenuItem(startRecordingMenuItem, false);
				ShowMenuItem(insertMarkerMenuItem, true);
				ShowMenuItem(saveMenuItem, false);
				ShowMenuItem(editMenuItem, false);
				ShowMenuItem(deleteMenuItem, false);
				ShowMenuItem(markerMenuItem, true);
				break;
			}
		}
	}

	/**
	 * Starts the {@link TrackListActivity}.
	 */
	private void startTrackListActivity()
	{
		startActivity(new Intent(this, TrackListActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
				| Intent.FLAG_ACTIVITY_NEW_TASK));
	}

	/**
	 * Starts the {@link SaveActivity} to save a track.
	 * 
	 * @param trackFileFormat
	 *          the track file format
	 * @param shareTrack
	 *          true to share the track after saving
	 */
	private void startSaveActivity(TrackFileFormat trackFileFormat, boolean shareTrack)
	{
		Intent intent = new Intent(this, SaveActivity.class).putExtra(SaveActivity.EXTRA_TRACK_ID, mTrackId).putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat).putExtra(SaveActivity.EXTRA_SHARE_TRACK, shareTrack);
		startActivity(intent);
	}

	/**
	 * Returns true if Google Earth app is installed.
	 */
	private boolean isEarthInstalled()
	{
		List<ResolveInfo> infos = getPackageManager().queryIntentActivities(new Intent().setType(SaveActivity.GOOGLE_EARTH_KML_MIME_TYPE), PackageManager.MATCH_DEFAULT_ONLY);
		for (ResolveInfo info : infos)
		{
			if (info.activityInfo != null && info.activityInfo.packageName != null
					&& info.activityInfo.packageName.equals(SaveActivity.GOOGLE_EARTH_PACKAGE))
			{
				return true;
			}
		}
		return false;
	}

	public void startRecording()
	{
		startNewRecording = true;
		trackRecordingServiceConnection.startAndBind();

		/*
		 * If the binding has happened, then invoke the callback to start a new
		 * recording. If the binding hasn't happened, then invoking the callback
		 * will have no effect. But when the binding occurs, the callback will get
		 * invoked.
		 */
		bindChangedCallback.run();
	}

	public void stopRecording()
	{
		TrackRecordingServiceConnectionUtils.stop(this, trackRecordingServiceConnection);

		if (recordingTrackId != -1L)
		{
			Intent intent = new Intent(this, TrackEditActivity.class).putExtra(TrackEditActivity.EXTRA_SHOW_CANCEL, false).putExtra(TrackEditActivity.EXTRA_TRACK_ID, recordingTrackId);
			startActivity(intent);
		}
	}

	public Activity getTabActivity(String aTag)
	{
		Activity ret = null;
		ret = getLocalActivityManager().getActivity(aTag);
		return ret;
	}

	@Override
	protected Dialog onCreateDialog(int id)
	{
		switch (id)
		{
			case DIALOG_CHART_SETTINGS:
				chartSettingsDialog = new ChartSettingsDialog(this);
				return chartSettingsDialog;
		}
		return null;
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog)
	{
		super.onPrepareDialog(id, dialog);
		switch (id)
		{
			case DIALOG_CHART_SETTINGS:
				chartSettingsDialog.setup();
				break;
		}
	}

	public static void deleteTrack(final long trackId)
	{

		AlertDialog dialog = null;
		AlertDialog.Builder builder = new AlertDialog.Builder(instance);
		builder.setMessage(instance.getString(R.string.track_detail_delete_confirm_message));
		builder.setTitle(instance.getString(R.string.are_you_sure_question));
		builder.setIcon(android.R.drawable.ic_dialog_alert);
		builder.setPositiveButton(instance.getString(R.string.generic_ok), new DialogInterface.OnClickListener()
		{
			public void onClick(DialogInterface dialog, int i)
			{
				dialog.dismiss();
				SportAssistantProviderUtils.Factory.get(instance).deleteTrack(trackId);
				instance.resetTrack();

				TrackListActivity mapList = (TrackListActivity) instance.getTabActivity(Constants.TAB_ITEM_TRACKS);
				mapList.resetList();
			}
		});
		builder.setNegativeButton(instance.getString(R.string.generic_cancel), new DialogInterface.OnClickListener()
		{
			public void onClick(DialogInterface dialog, int i)
			{
				dialog.dismiss();
			}
		});
		dialog = builder.create();
		dialog.show();

	}

	public void updateTrack(final long trackId)
	{
		Track track = SportAssistantProviderUtils.Factory.get(instance).getTrack(trackId);
		SportAssistantProviderUtils.Factory.get(instance).updateTrack(track);
	}

	public void showDialogSafely(final int id)
	{
		runOnUiThread(new Runnable()
		{
			public void run()
			{
				try
				{
					showDialog(id);
				}
				catch (BadTokenException e)
				{
					Log.w(TAG, "Could not display dialog with id " + id, e);
				}
				catch (IllegalStateException e)
				{
					Log.w(TAG, "Could not display dialog with id " + id, e);
				}
			}
		});
	}

	public void resetTrack()
	{
		trackDataHub.unloadCurrentTrack();
	}

	public boolean isRecording()
	{
		return TrackRecordingServiceConnectionUtils.isRecording(this, trackRecordingServiceConnection);
	}

}